import {BaseSession} from "../base";
import {
    BoolValue,
    FloatValue,
    fromAny,
    Int32Value,
    StringValue,
    toAny,
} from "../../proto";
import {WidgetFileUploaderSession} from "../widgets/fileUploader";
import {MediaRecorderSession} from "./recorder";

export class MediaPlayerSession extends BaseSession {
    private player: HTMLAudioElement;

    constructor(render: HTMLElement) {
        super("MediaPlayer", render);
    }

    onReceive(name: String, sessionId: number, futureId: number, ...argv) {
        switch (name) {
            case "load":
                return this.load(sessionId, futureId, ...argv)
            case "loadFromWidgetFileUploader":
                return this.loadFromWidgetFileUploader(sessionId, futureId, ...argv)
            case "loadFromMediaRecorder":
                return this.loadFromMediaRecorder(sessionId, futureId, ...argv)
            case "play":
                return this.play()
            case "stop":
                return this.stop(sessionId, futureId)
            case "pause":
                return this.pause()
            case "setOnCompletionListener":
                return this.setOnCompletionListener(...argv)
            case "setLooping":
                return this.setLooping(...argv)
            case "setSpeed":
                return this.setSpeed(...argv)
            case "setVolume":
                return this.setVolume(...argv)
            case "seekTo":
                return this.seekTo(...argv)
            case "isPlaying":
                return this.getIsPlaying(sessionId, futureId)
            case "duration":
                return this.getDuration(sessionId, futureId)
            case "currentPosition":
                return this.getCurrentPosition(sessionId, futureId)
        }
        super.onReceive(name, sessionId, futureId, ...argv);
    }

    onCreate(sessionId: number, futureId: number, ...argv) {
        super.onCreate(sessionId, futureId, ...argv);
        this.player = document.createElement("audio");
    }

    onDestroy() {
        this.player.pause();
        // this.player = null;
        super.onDestroy();
    }

    private load(sessionId: number, futureId: number, ...argv) {
        this.player.src = fromAny(argv[0], StringValue)
        this.sendAction("onLoad", sessionId, futureId, argv[0]);
    }

    private async loadFromWidgetFileUploader(sessionId: number, futureId: number, ...argv) {
        const uploader = this.getReference<WidgetFileUploaderSession>(argv[0])
        uploader.listenFileSourceChange(url => this.player.src = url)
        this.sendAction("onLoadFromWidgetFileUploader", sessionId, futureId, toAny(true, BoolValue))
    }
    private async loadFromMediaRecorder(sessionId: number, futureId: number, ...argv) {
        const recorder = this.getReference<MediaRecorderSession>(argv[0])
        recorder.listenRecorded(url => this.player.src = url)
        this.sendAction("onLoadFromMediaRecorder", sessionId, futureId, toAny(true, BoolValue))
    }

    private  play() {
        this.player.play().then(_ => {});
    }

    private setOnCompletionListener(...argv) {
        this.player.onended = () => this.sendCallback(argv[0])
    }

    private stop(sessionId: number, futureId: number) {
        if (this.player) {
            this.player.pause();
            this.player.currentTime = 0;
            this.sendAction("onStop", sessionId, futureId, toAny(true, BoolValue));
        }
        this.sendAction("onStop", sessionId, futureId, toAny(false, BoolValue));
    }

    private pause() {
        this.player.pause();
    }

    private setLooping(...argv) {
        this.player.loop = fromAny(argv[0], BoolValue)
    }

    private setSpeed(...argv) {
        this.player.playbackRate = fromAny(argv[0], FloatValue);
    }

    private setVolume(...argv) {
        this.player.volume = fromAny(argv[0], FloatValue);
    }

    private seekTo(...argv) {
        this.player.currentTime = fromAny(argv[0], Int32Value) / 1000;
    }

    private getIsPlaying(sessionId: number, futureId: number) {
        const isPlaying = toAny(!this.player.paused, BoolValue);
        this.sendAction("onIsPlaying", sessionId, futureId, isPlaying);
    }

    private getDuration(sessionId: number, futureId: number) {
        const dms = toAny(!this.player.duration, Int32Value);
        this.sendAction("onDuration", sessionId, futureId, dms);
    }

    private getCurrentPosition(sessionId: number, futureId: number) {
        const cms = toAny(this.player.currentTime * 1000, Int32Value);
        this.sendAction("onCurrentPosition", sessionId, futureId, cms);
    }
}
